package moga.ui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

import moga.logic.TestFunctions;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.RefineryUtilities;
import java.awt.BorderLayout;
import java.io.File;
import java.io.IOException;
import java.util.Vector;

import javax.swing.JButton;

public class Grafico extends JPanel implements ActionListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = -6383792098731421408L;
	Class<? extends Grafico> clase  = this.getClass();
	
	JFreeChart chart;
	ChartPanel chartPanel;
	XYDataset dataset;
	XYSeriesCollection collectionSeries;
	XYSeries serieGA;
	XYSeries serieFunction;
	XYSeries seriePareto;
	XYPlot plot;
	JButton btnGuardar;
	double interval=0.01;
	JFileChooser fc;
	
	XYLineAndShapeRenderer renderer;

	Grafico() {
		this.fc = new JFileChooser();
		this.serieFunction = new XYSeries("Functions");
		this.serieGA       = new XYSeries("Ajuste GA");
		this.seriePareto   = new XYSeries("Pareto");
		
		this.collectionSeries = new XYSeriesCollection();	
		this.collectionSeries.addSeries(this.serieGA);
		this.collectionSeries.addSeries(this.seriePareto);
		this.collectionSeries.addSeries(this.serieFunction);
		
		
		this.chart = createChart(collectionSeries);
		this.chartPanel = new ChartPanel(chart);
		
		this.btnGuardar = new JButton("Guardar Imagen");
		this.btnGuardar.addActionListener(this);
		JPanel panelBtn = new JPanel(new FlowLayout());
		panelBtn.add(btnGuardar);
		
		this.setLayout(new BorderLayout(0, 0));
		this.add(chartPanel, BorderLayout.CENTER);
		this.add(panelBtn, BorderLayout.SOUTH);
		
		 this.plot = (XYPlot) chart.getPlot();
	     this.renderer = new XYLineAndShapeRenderer();
	     
	     this.renderer.setSeriesLinesVisible(0, false);
	     this.renderer.setSeriesShapesVisible(0, true);	
		 
	     this.renderer.setSeriesLinesVisible(1, false);
	     this.renderer.setSeriesShapesVisible(1, true);
		 
	     this.renderer.setSeriesLinesVisible(2, true);
	     this.renderer.setSeriesShapesVisible(2, false);
	     this.renderer.setSeriesPaint(2, Color.BLACK);
		 
		 this.plot.setRenderer(this.renderer);
	}
	
	
	public synchronized void setRangeAxis(double upper,  double lower){
		final NumberAxis rangeAxis = (NumberAxis) this.plot.getRangeAxis();
        rangeAxis.setUpperBound(upper);
        rangeAxis.setLowerBound(lower);
	}

	public synchronized void cleanSerieGA(){
		System.out.println(clase+" cleanSerieGA() Iniciado... ");
		this.serieGA.clear();
		this.chart.fireChartChanged();
		//this.chartPanel.update(this.chartPanel.getGraphics());
		System.out.println(clase+" cleanSerieGA() Terminado... ");
	}
	
	public synchronized void cleanSeriePareto(){
		System.out.println(clase+" cleanSeriePareto() Iniciado... ");
		this.seriePareto.clear();
		this.chart.fireChartChanged();
		System.out.println(clase+" cleanSeriePareto() Termiando... ");
	}
	
	public synchronized void updateSeries(){
		System.out.println(clase+" updateSeries() Iniciado... ");
		this.chart.fireChartChanged();
		//this.chartPanel.update(this.chartPanel.getGraphics());
		System.out.println(clase+" updateSeries() Termiando... ");
	}
	
	public synchronized void addPointGA(double dblX, double dblY) {
		this.serieGA.add(dblX, dblY);
	}
	
	
	public synchronized void addPointPareto(double dblX, double dblY) {
		this.seriePareto.add(dblX, dblY);
	}
	
	public synchronized void showSeries(int index, boolean blnShow){
		this.renderer.setSeriesVisible(index, blnShow);
	}

	private JFreeChart createChart(final XYDataset dataset) {

		// create the chart...
		final JFreeChart chart = ChartFactory.createXYLineChart("Funciones...", // chart
																						// title
				"f1", // x axis label
				"f2", // y axis label
				dataset, // data
				PlotOrientation.VERTICAL, true, // include legend
				true, // tooltips
				false // urls
				);

		return chart;
	}
	
	public void actionPerformed(ActionEvent evt) {
		if (evt.getSource() == this.btnGuardar) {
			this.saveImagen("");
		}
	}
	
	public void saveImagen(String strFile) {
		if (strFile == null || strFile.trim().equals("")) {
			int returnVal = fc.showSaveDialog(this);
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				try {
					strFile = fc.getSelectedFile().getAbsolutePath();
					strFile = strFile.toLowerCase();
					if (!strFile.contains(".png")) {
						strFile += ".png";
					}

					File file = new File(strFile);
					ChartUtilities.saveChartAsPNG(file, this.chart, 400, 250);
				} catch (Exception ex) {
					System.out.println(ex);
				}
			}
		}
		else{
			strFile = strFile.toLowerCase();
			if (!strFile.endsWith(".png")) {
				strFile += ".png";
			}
			File file = new File(strFile);
			try {
				ChartUtilities.saveChartAsPNG(file, this.chart, 400, 250);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	
	public void paintTestFunction(Vector<double[]> points, String strName){
		this.collectionSeries.removeSeries(serieFunction);
		this.serieFunction = new XYSeries(strName);
		
		for(int i=0; i<points.size(); i++){
			double point[] = points.get(i);
			this.serieFunction.add(point[0], point[1]);
		}
		this.collectionSeries.addSeries(this.serieFunction);
		this.chart.fireChartChanged();
		//this.chartPanel.update(this.chartPanel.getGraphics());
	}
	
	
	
	public static void main(final String[] deflt) {

		final Grafico demo = new Grafico();
		JFrame frame = new JFrame();
		frame.setContentPane(demo);
		frame.setSize(new Dimension(520, 320));
		frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

		RefineryUtilities.centerFrameOnScreen(frame);
		TestFunctions functions = new TestFunctions();
		functions.setInterval(0.01);
		
		frame.setVisible(true);
		Vector<double[]> puntos;
		
		try {
			puntos = functions.function1();
			demo.paintTestFunction(puntos, "Funcion 1");
			Thread.sleep(1500);
			
			puntos = functions.function2();
			demo.paintTestFunction(puntos, "Funcion 2");
			Thread.sleep(1500);
			
			puntos = functions.function3();
			demo.paintTestFunction(puntos, "Funcion 3");
			Thread.sleep(1500);
			
			puntos = functions.function4();
			demo.paintTestFunction(puntos, "Funcion 4");
			Thread.sleep(1500);
			
			puntos = functions.function5();
			demo.paintTestFunction(puntos, "Funcion 5");
			Thread.sleep(1500);
			
			puntos = functions.function6();
			demo.paintTestFunction(puntos, "Funcion 6");
			Thread.sleep(1500);
			
			puntos = functions.function3();
			demo.paintTestFunction(puntos, "Funcion 3");
			
			for (int k=0; k<100;k++){
				for(int i=0;i<10; i++){
					demo.addPointGA(Math.random(), Math.random());
				}
				
				for(int i=0;i<6; i++){
					demo.addPointPareto(Math.random(), Math.random());
				}
				
				demo.updateSeries();
				System.out.println("Durmiendo: "+ (k+1));
				Thread.sleep(100);
				
				demo.cleanSerieGA();	
				demo.cleanSeriePareto();
			}
		} 
		catch (InterruptedException e) {
			e.printStackTrace();
		}
		
	}
}
